package cn.teawooo.tree;

import cn.teawooo.log.LocalizationLogger;
import cn.teawooo.log.LoggerFactory;
import cn.teawooo.tree.node.Node;

/**
 * 功能描述：抽象树
 * @author teawooo <long1795@gmail.com>
 * @time 2013年8月26日 下午2:31:30
 */
@SuppressWarnings("unchecked")
public abstract class AbstractTree<T extends Node<?>> implements Tree<T> {

    /**
     * 本地化日志输出器
     */
    protected LocalizationLogger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 根
     */
    protected T root;

    /**
     * 默认构建
     */
    protected AbstractTree() {
    }

    /**
     * 指定根节点 构建
     * @param root 根
     */
    protected AbstractTree(T root) {
        this.root = root;
    }

    @Override
    public void setRoot(T root) {
        this.root = root;
    }

    @Override
    public T getRoot() {
        return root;
    }

    @Override
    public T getNode(String name) {
        if (root == null || name == null) {
            return null;
        }
        return getNodeByName(root, name);
    }

    private T getNodeByName(T t, String name) {
        if (t == null || name == null) {
            return null;
        }
        if (name.equals(t.getName())) {
            return t;
        }
        if (t.getChildren() == null) {
            return null;
        }
        for (Node<?> c : t.getChildren()) {
            T r = getNodeByName((T) c, name);
            if (r != null) {
                return r;
            }
        }
        return null;
    }

    /**
     * 获取默认迭代器
     * @return 默认迭代器
     */
    abstract protected TreeIterator<T> getDefaultIterator();

    @Override
    public void iterate() {
        iterate(getDefaultIterator());
    }

    @Override
    public void iterate(TreeIterator<T> iterator) {
        if (root == null) {
            return;
        }
        doIterate(iterator, root, 0);
    }

    /**
     * 迭代
     * @param iterator 迭代器
     * @param node 节点
     * @param currLevel 当前层级
     */
    private void doIterate(TreeIterator<T> iterator, T node, int currLevel) {
        iterator.doIterateImpl(node, currLevel);
        if (node.isLeaf()) {
            return;
        }
        for (Node<?> c : node.getChildren()) {
            doIterate(iterator, (T) c, currLevel + 1);
        }
    }

}
